/**
 * 封装 http 请求
 * node 环境 axios cookie 保持 ：
 * https://www.npmjs.com/package/axios-cookiejar-support
 * https://blog.csdn.net/sdfgjhdgh/article/details/105205238
 *
 <pre>
 // 新建一个<script>标签
 var importJs=document.createElement('script');
 // 引入 axios.js
 importJs.setAttribute('src', 'https://cdn.bootcss.com/axios/0.21.1/axios.js');
 // 将<script>标签加入<head>
 document.getElementsByTagName("head")[0].appendChild(importJs);
 // 发起 get 请求
 axios.get('/').then(res=>console.log(res)).catch(e=>console.error(e))
 </pre>
 *
 * @author 谢长春 2019-7-28
 */
import axios from 'axios'
import isNull from 'lodash/isNull'
import isObject from 'lodash/isObject'
import isArray from 'lodash/isArray'
import isEmpty from 'lodash/isEmpty'
import isNumber from 'lodash/isNumber'
import isString from 'lodash/isString'
import qs from 'qs'
import Aes from '../utils/Aes'
import UserService from './UserService'

const buildSearchParams = params => {
  // url 带参如果包含对象，需要经过转换，变成字符串，否则 axios 会出错
  if (!isEmpty(params)) {
    const searchParams = JSON.parse(JSON.stringify(params, (key, value) => {
      if (!key) { // key === '' 表示根对象
        return value
      }
      if (isNull(value)) return undefined
      if (isString(value) && value.trim() === '') return undefined
      if (isArray(value)) {
        if (isEmpty(value)) return undefined
        if (isString(value[0]) || isNumber(value[0])) {
          return value.join(',')
        }
        return JSON.stringify(value)
      }
      if (isObject(value)) {
        if (isEmpty(value)) return undefined
        return JSON.stringify(value)
      }
      return value
    }))
    return qs.stringify(searchParams)
  }
  return ''
}
const http = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // 请求前缀
  withCredentials: process.env.NODE_ENV === 'development', // 允许跨域，否则开发环境每次刷新页面都会路由到登录页
  headers: {'X-VERSION': process.env.VUE_APP_VERSION || '1.0.0'}, // 前端版本号
  paramsSerializer: buildSearchParams
})
http.interceptors.request.use((request) => {
  // 请求头追加token
  request.headers = Object.assign({}, request.headers, UserService.getToken())
  return request
})
if (process.env.GULPFILE) { // gulp 环境保持 cookie , 支持 csrf
  const tough = require('tough-cookie')
  const Cookie = tough.Cookie
  const cookies = {}
  http.interceptors.request.use(function(config) {
    config.headers.cookie = Object.keys(cookies).map(key => `${key}=${cookies[key]}`).join('; ')
    if (cookies['XSRF-TOKEN']) {
      config.headers = Object.assign(config.headers, {'X-XSRF-TOKEN': cookies['XSRF-TOKEN']})
    } else if (cookies['X-XSRF-TOKEN']) {
      config.headers = Object.assign(config.headers, {'X-XSRF-TOKEN': cookies['X-XSRF-TOKEN']})
    } else if (cookies['CSRF-TOKEN']) {
      config.headers = Object.assign(config.headers, {'X-CSRF-TOKEN': cookies['CSRF-TOKEN']})
    } else if (cookies['X-CSRF-TOKEN']) {
      config.headers = Object.assign(config.headers, {'X-CSRF-TOKEN': cookies['X-CSRF-TOKEN']})
    }
    return config
  })

  http.interceptors.response.use(function(response) {
    if (response.headers['set-cookie'] instanceof Array) {
      response.headers['set-cookie'].forEach(c => {
        const obj = Cookie.parse(c).toJSON()
        cookies[obj.key] = obj.value
      })
    }
    return response
  })
}
/**
 * 开发环境 http 请求配置
 */
if (process.env.NODE_ENV === 'development') {
  http.interceptors.request.use(config => { // request 拦截器，拦截请求参数，打印日志
    // if (process.env.NODE_ENV === 'development') {
    //   console.log(config)
    // }
    const {
      method,
      baseURL,
      url,
      params,
      data
    } = config
    if (method.toUpperCase() === 'GET') {
      const searchParams = buildSearchParams(params)
      console.log(JSON.stringify([`${method.toUpperCase()} ${baseURL}${url}${searchParams ? `?${searchParams}` : ''}`, params]))
    } else if (((config.headers || {})['content-type'] || '').startsWith('multipart/form-data;')) {
      console.log(JSON.stringify([`${method.toUpperCase()} ${baseURL}${url}`]))
    } else {
      console.log(JSON.stringify([`${method.toUpperCase()} ${baseURL}${url}`, data]))
    }
    return config
  })

// http.defaults.proxy = {
//   host: '127.0.0.1',
//   port: 8080
//   // auth: {username: 'admin', password: 'admin'}
// }
// GET 请求参数格式化策略
// http.defaults.paramsSerializer = params => {
//     console.log({params: params});
//     return encodeURI(JSON.stringify({json: params}))
// };
// POST|PUT|PATCH|DELETE 请求参数格式化策略
// http.defaults.transformRequest = data => {
//     console.log({data: data});
//     return data && Qs.stringify({json: data});
// };
// // 响应对象装换
// http.defaults.transformResponse = data => {
//     console.log({resData: data});
//     return data
// };
// http.defaults.withCredentials = true; // 允许跨域
// http.defaults.proxy = { // 代理后端接口
//     host: '127.0.0.1',
//     port: 8080
//     // auth: {username: 'admin', password: 'admin'}
// }
}
// 响应拦截
// http.interceptors.response.use(
//   response => {
//     const {code} = response.data
//     if (code === 'A00003') {
//     } else {
//       return response
//     }
//   }
// )
if (process.env.VUE_APP_AES_ENABLED === 'YES') { // Api 接口响应数据加解密开关
  http.interceptors.request.use((request) => {
    if (!request.data) { // 请求体为空时不加密
      return request
    }
    if (((request.headers || {})['content-type'] || '').startsWith('multipart/form-data;')) { // 上传文件不加密
      return request
    }
    // 请求 body 数据加密
    request.headers = Object.assign({}, request.headers, {'content-type': 'application/json'})
    request.data = Aes.encrypt(JSON.stringify(request.data))
    return request
  })
  http.interceptors.response.use((response) => {
    if (response.status === 200) { // 响应 body 数据解密
      if (response.data) {
        // console.log(['response ', response.status, response.data])
        response.data = JSON.parse(Aes.decrypt(response.data))
        // console.log(['response decrypt', response.data])
      }
    }
    return response
  })
}

/**
 * 设置响应拦截器
 * @param interceptor {function}
 */
export const setRequestInterceptor = (interceptor = request => {
}) => {
  http.interceptors.request.use(interceptor)
}

/**
 * 设置响应拦截器
 * @param interceptor {function}
 */
export const setResponseInterceptor = (interceptor = response => {
}) => {
  http.interceptors.response.use(interceptor)
}

export default http
